﻿using System;
using System.IO;
using Moonlite.ExtensionApi.ControlInterfaces;
using Moonlite.ExtensionApi.GlobalInterfaces;
namespace Moonlite.Services.CodeCompletion
{
    public static class GalaxyObjectHelper
    {
        public static AndromedaSource GetSourceFromFileName(string filename, AndromedaStructure structure)
        {
            if (structure != null)
            {
                foreach (AndromedaSource source in structure.Sources)
                {
                    Uri filenameUri = new Uri(filename);
                    Uri sourcePathUri = new Uri(source.Path);
                    if (filenameUri.AbsolutePath == sourcePathUri.AbsolutePath)
                    {
                        return source;
                    }
                }
            }

            return null;
        }

        public static IProjectFile GetFileFromSource(AndromedaSource source, IProject project)
        {
            if (source != null)
            {
                foreach (IProjectFile file in project.GetAllFiles())
                {
                    if (file.Path == source.Path)
                    {
                        return file;
                    }
                }
            }

            return null;
        }

        public static AndromedaObject GetOopObjectFromName(string name, AndromedaObject parent, out AndromedaObjectOopType type)
        {
            if (parent != null)
            {
                foreach (AndromedaObject @object in parent.GetAllChildren())
                {
                    if (@object is AndromedaObjectClass)
                    {
                        if (((AndromedaObjectClass)@object).Name == name)
                        {
                            type = AndromedaObjectOopType.Class;
                            return @object;
                        }
                    }
                    else if (@object is AndromedaObjectEnrichment)
                    {
                        if (((AndromedaObjectEnrichment)@object).Name == name)
                        {
                            type = AndromedaObjectOopType.Enrichment;
                            return @object;
                        }
                    }
                    else if (@object is AndromedaObjectStruct)
                    {
                        if (((AndromedaObjectStruct)@object).Name == name)
                        {
                            type = AndromedaObjectOopType.Struct;
                            return @object;
                        }
                    }
                }
            }

            type = AndromedaObjectOopType.None;
            return null;
        }

        public static AndromedaObjectMethod GetCurrentMethod(AndromedaObject parent, ITextEditor textEditor, int TagLength)
        {
            if (parent is AndromedaObjectWithSpecificChildren)
            {
                foreach (AndromedaObjectMethod @object in ((AndromedaObjectWithSpecificChildren)parent).GetAllMethods())
                {
                    if (textEditor.InnerTextEditor.Caret.Offset + TagLength >= @object.Offset && textEditor.InnerTextEditor.Caret.Offset + TagLength <= @object.Offset + @object.Length)
                    {
                        return @object;
                    }
                }
            }
            else
            {
                foreach (AndromedaObject @object in parent.GetAllChildren())
                {
                    if (textEditor.InnerTextEditor.Caret.Offset + TagLength >= @object.Offset && textEditor.InnerTextEditor.Caret.Offset + TagLength <= @object.Offset + @object.Length)
                    {
                        if (@object is AndromedaObjectMethod) return (AndromedaObjectMethod)@object;
                    }
                }
            }

            return null;
        }

        public static AndromedaObjectProperty GetCurrentProperty(AndromedaObject parent, ITextEditor textEditor, int TagLength)
        {
            if (parent is AndromedaObjectWithSpecificChildren)
            {
                foreach (AndromedaObjectProperty @object in ((AndromedaObjectWithSpecificChildren)parent).GetAllProperties())
                {
                    if (textEditor.InnerTextEditor.Caret.Offset + TagLength >= @object.Offset && textEditor.InnerTextEditor.Caret.Offset + TagLength <= @object.Offset + @object.Length)
                    {
                        return @object;
                    }
                }
            }
            else
            {
                foreach (AndromedaObject @object in parent.GetAllChildren())
                {
                    if (textEditor.InnerTextEditor.Caret.Offset + TagLength >= @object.Offset && textEditor.InnerTextEditor.Caret.Offset + TagLength <= @object.Offset + @object.Length)
                    {
                        if (@object is AndromedaObjectProperty) return (AndromedaObjectProperty)@object;
                    }
                }
            }

            return null;
        }

        public static AndromedaObjectField GetCurrentField(AndromedaObject parent, ITextEditor textEditor, int TagLength)
        {
            if (parent is AndromedaObjectWithSpecificChildren)
            {
                foreach (AndromedaObjectField @object in ((AndromedaObjectWithSpecificChildren)parent).GetAllFields())
                {
                    if (textEditor.InnerTextEditor.Caret.Offset + TagLength >= @object.Offset && textEditor.InnerTextEditor.Caret.Offset + TagLength <= @object.Offset + @object.Length)
                    {
                        return @object;
                    }
                }
            }
            else
            {
                foreach (AndromedaObject @object in parent.GetAllChildren())
                {
                    if (textEditor.InnerTextEditor.Caret.Offset + TagLength >= @object.Offset && textEditor.InnerTextEditor.Caret.Offset <= @object.Offset + TagLength + @object.Length)
                    {
                        if (@object is AndromedaObjectField) return (AndromedaObjectField)@object;
                    }
                }
            }

            return null;
        }

        public static AndromedaObjectClass GetCurrentClass(AndromedaObject parent, ITextEditor textEditor, int TagLength)
        {
            if (parent is AndromedaObjectWithSpecificChildren)
            {
                foreach (AndromedaObjectClass @object in ((AndromedaObjectWithSpecificChildren)parent).GetAllClasses())
                {
                    if (textEditor.InnerTextEditor.Caret.Offset + TagLength >= @object.Offset && textEditor.InnerTextEditor.Caret.Offset + TagLength <= @object.Offset + @object.Length)
                    {
                        return @object;
                    }
                }
            }
            else
            {
                foreach (AndromedaObject @object in parent.GetAllChildren())
                {
                    if (textEditor.InnerTextEditor.Caret.Offset + TagLength >= @object.Offset && textEditor.InnerTextEditor.Caret.Offset + TagLength <= @object.Offset + @object.Length)
                    {
                        if (@object is AndromedaObjectClass) return (AndromedaObjectClass)@object;
                    }
                }
            }

            return null;
        }

        public static AndromedaObjectEnrichment GetCurrentEnrichment(AndromedaObject parent, ITextEditor textEditor, int TagLength)
        {
            if (parent is AndromedaObjectWithSpecificChildren)
            {
                foreach (AndromedaObjectEnrichment @object in ((AndromedaObjectWithSpecificChildren)parent).GetAllEnrichments())
                {
                    if (textEditor.InnerTextEditor.Caret.Offset + TagLength >= @object.Offset && textEditor.InnerTextEditor.Caret.Offset + TagLength <= @object.Offset + @object.Length)
                    {
                        return @object;
                    }
                }
            }
            else
            {
                foreach (AndromedaObject @object in parent.GetAllChildren())
                {
                    if (textEditor.InnerTextEditor.Caret.Offset + TagLength >= @object.Offset && textEditor.InnerTextEditor.Caret.Offset + TagLength <= @object.Offset + @object.Length)
                    {
                        if (@object is AndromedaObjectEnrichment) return (AndromedaObjectEnrichment)@object;
                    }
                }
            }

            return null;
        }

        public static AndromedaObjectStruct GetCurrentStruct(AndromedaObject parent, ITextEditor textEditor, int TagLength)
        {
            if (parent is AndromedaObjectWithSpecificChildren)
            {
                foreach (AndromedaObjectStruct @object in ((AndromedaObjectWithSpecificChildren)parent).GetAllStructs())
                {
                    if (textEditor.InnerTextEditor.Caret.Offset + TagLength >= @object.Offset && textEditor.InnerTextEditor.Caret.Offset + TagLength <= @object.Offset + @object.Length)
                    {
                        return @object;
                    }
                }
            }
            else
            {
                foreach (AndromedaObject @object in parent.GetAllChildren())
                {
                    if (textEditor.InnerTextEditor.Caret.Offset + TagLength >= @object.Offset && textEditor.InnerTextEditor.Caret.Offset + TagLength <= @object.Offset + @object.Length)
                    {
                        if (@object is AndromedaObjectStruct) return (AndromedaObjectStruct)@object;
                    }
                }
            }

            return null;
        }

        public static bool InterfaceFilter(Type typeObj, object criteriaObj)
        {
            return true;
        }

        public static AndromedaObject GetCurrentObject(AndromedaObject parent, ITextEditor textEditor, Type[] types, int TagLength)
        {
            AndromedaObject currentObject = null;
            foreach (AndromedaObject @object in parent.Children)
            {
                if (textEditor.InnerTextEditor.Caret.Offset + TagLength >= @object.Offset && textEditor.InnerTextEditor.Caret.Offset + TagLength <= @object.Offset + @object.Length)
                {
                    bool shouldContinue = true;
                    if (types != null)
                    {
                        shouldContinue = false;
                        Type objectType = @object.GetType();
                        Type[] interfaces = objectType.FindInterfaces(InterfaceFilter, null);
                        foreach (Type type in types)
                        {
                            bool correctInterface = false;
                            foreach (Type interfaceType in interfaces)
                            {
                                if (interfaceType == type)
                                {
                                    correctInterface = true;
                                    break;
                                }
                            }

                            if (objectType == type || objectType.IsSubclassOf(type) || correctInterface)
                            {
                                shouldContinue = true;
                                break;
                            }
                        }
                    }

                    if (shouldContinue)
                    {
                        currentObject = @object;
                    }

                    AndromedaObject childCurrentObject = GetCurrentObject(@object, textEditor, types, TagLength);
                    if (childCurrentObject != null)
                    {
                        currentObject = childCurrentObject;
                    }
                }
            }

            return currentObject;
        }
    }
}
